<template>
  <el-table ref="z-virtual-table"
            :class="`z-virtual-table-${tableId}`"
            v-bind="{
              ...$attrs,
              rowStyle: rowStyle,
              data: list,
            }"
            v-on="$listeners">
    <slot></slot>
  </el-table>
</template>

<script>
import { v4 } from 'uuid'
export default {
  name: 'ZVirtualTable',
  props: {
    value: {
      type: Array,
      default: () => []
    },
    itemHeight: {
      type: Number,
      default: 53
    },
    size: {
      type: Number,
      default: 14
    }
  },
  data () {
    return {
      list: [],
      body: null,
      tableId: v4(),
      position: null,
      page: 0,

      scrollTop: 0,
      start: 0,
      end: 3 * this.size
    }
  },

  created () {
    this.init()
  },
  mounted () {
    this.$nextTick(() => {
      this.body = this.$refs['z-virtual-table'].bodyWrapper

      let wrapper = document.createElement('div')
      wrapper.style.height = `${this.value.length * this.itemHeight}px`
      let position = document.createElement('div')
      position.className = `z-virtual-table-${this.tableId}__position`
      position.append(this.body.children[0])
      wrapper.append(position)
      this.body.append(wrapper)
      this.position = document.querySelector(
        `.z-virtual-table-${this.tableId}.el-table .el-table__body-wrapper .z-virtual-table-${this.tableId}__position`
      )

      this.body.addEventListener('scroll', this.scroll)
    })
  },
  methods: {
    rowStyle (row, rowIndex) {
      const { rowStyle } = this.$attrs
      let styles = {
        height: `${this.itemHeight}px`
      }
      if (rowStyle) {
        styles = Object.assign({}, styles, rowStyle(row, rowIndex))
      }

      return styles
    },
    init () {
      this.list = this.value.slice(this.start, this.end)
    },
    scroll () {
      this.scrollTop = this.body.scrollTop
      this.page = Math.floor(this.scrollTop / (this.itemHeight * this.size))
    }
  },
  watch: {
    page (val) {
      if (val > 1) {
        this.start = (val - 1) * this.size
        this.end = (val + 2) * this.size
        this.position.style.transform = `translateY(${this.start * this.itemHeight
        }px)`
        this.list = this.value.slice(this.start, this.end)
      } else {
        this.start = 0
        this.end = this.size * 3
        this.list = this.value.slice(this.start, this.end)
        this.position.style.transform = `translateY(0px)`
      }
    }
  },
  destroyed () {
    this.body.removeEventListener('scroll', this.scroll)
  }
}
</script>
